<?php
/**
 * Author: ChenGuangHui
 * Email：13035809409@163.com
 * Date Time: 2021/5/13 16:52
 */

namespace App\Logic\Goods;


use App\Enums\HttpCode;
use App\Logic\CommLogic;
use App\Models\Store\Cart;
use Illuminate\Database\Eloquent\Builder;
use App\Models\Store\Goods;
use App\Models\Store\GoodsSku;
use App\Models\Store\GoodsSpec;
use App\Models\Store\Spec;
use App\Models\Store\SpecValue;
use Exception;
use Illuminate\Database\QueryException;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

class GoodsLogic extends CommLogic
{
    /**
     * @author ChenGuangHui
     * @dateTime 2022-05-17
     * @param  [type] $params
     */
    public function lists($params)
    {
        $query = Goods::query()
        ->when(isset($where['status']), function (Builder $query) use ($params) {
            $query->where('status', $params['status']);
        })
        ->when(isset($where['goods_type']), function (Builder $query) use ($params) {
            $query->where('goods_type', $params['goods_type']);
        })
        ->when(!empty($params['name']), function (Builder $query) use ($params) {
            $query->where('goods_name', 'like', '%' . $params['name'] . '%');
        })
        ->when(!empty($params['goods_ids']), function (Builder $query) use ($params) {
            $query->whereIn('goods_id', explode(',', $params['goods_ids']));
        });

        if (!empty($sortData)) {
            $query = $query->orderBy($sortData['sortRow'], $sortData['sortType']);
        }else{
            $query = $query->orderBy('goods_id', 'desc');
        }

        $data = $query->get()->toArray();

        foreach($data as &$item){
            if (!empty($item['goods_cover'])) {
                $item['goods_cover'] = Arr::first(array_column(json_decode($item['goods_cover'], true), 'url'));
            }
            $item['goods_thumb'] = Arr::first(array_column(json_decode($item['goods_thumb'], true), 'url'));
        }
        return $data;
    }
    
    /**
     * @param array $where
     * @param array $pageData
     * @param array $sortData
     * @return \Illuminate\Http\JsonResponse
     */
    public function index($where = [], $pageData = ['pageSize' => 20, 'pageNow' => 1], $sortData = [])
    {
        $query = Goods::query()
            ->when(isset($where['status']), function (Builder $query) use ($where) {
                $query->where('status', $where['status']);
            })
            ->when(!empty($where['name']), function (Builder $query) use ($where) {
                $query->where('goods_name', 'like', '%' . $where['name'] . '%');
            })
            ->when(isset($where['goods_type']), function (Builder $query) use ($where) {
                $query->where('goods_type', $where['goods_type']);
            });

        if (!empty($sortData)) {
            $query = $query->orderBy($sortData['sortRow'], $sortData['sortType']);
        }else{
            $query = $query->orderBy('goods_id', 'desc');
        }
        $data = $query->paginate($pageData['pageSize'], ['*'], 'page', $pageData['pageNow'])->toArray();

        foreach($data['data'] as &$item){
            if (!empty($item['goods_cover'])) {
                $item['goods_cover'] = Arr::first(array_column(json_decode($item['goods_cover'], true), 'url'));
            }
            $item['goods_thumb'] = Arr::first(array_column(json_decode($item['goods_thumb'], true), 'url'));
        }

        return $data;
    }

    /**
     * @param $params
     * @return \App\Models\Model|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
     */
    public function store($params)
    {
        $lockName = 'goods_store_' . auth('api')->id();
        $lock = \Cache::lock($lockName, 5);
        abort_if(!$lock->get(), HttpCode::TOO_MANY_REQUESTS, '请勿重复操作！');
        \DB::beginTransaction();
        try {
            $data = array(
                'goods_name' => $params['goods_name'],
                'goods_price' => $params['goods_price'],
                'line_price' => $params['line_price'],
                'goods_no' => $params['goods_no'],
                'goods_type' => $params['goods_type'],
                'status' => $params['status'],
                'sort' => $params['sort'] ?? 0,
                'title' => $params['title'] ?? '',
                'freight_id' => $params['freight_id'],
                'service_ids' => implode(',', $params['service_ids']),
                'gift_growth' => $params['gift_growth'] ?? 0,
                'gift_point' => $params['gift_point'] ?? 0,
                'use_point_limit' => $params['use_point_limit'] ?? 0,
                'limit_num' => $params['limit_num'] ?? 0,
                'stock_num' => !empty($params['sku']) ? array_sum(array_column($params['sku'], 'stock_num')) : 0,
                'goods_cover' => isset($params['goods_cover']) ? json_encode($params['goods_cover'], true) : '',
                'goods_thumb' => json_encode($params['goods_thumb'], true),
                'goods_video' => isset($params['goods_video']) ? json_encode($params['goods_video'], true) : '',
                'content' => $params['content'],
                'md_content' => $params['md_content'],
            );
            $goods = Goods::query()->create($data);
            // 属性
            foreach($params['attribute'] as $val){
                $spec = Spec::query()->firstOrCreate(['spec_name' => $val['name']]);
                foreach($val['item'] as $item){
                    SpecValue::query()->firstOrCreate(['spec_id' => $spec->getQueueableId(), 'spec_value' => $item]);
                }
            }
            // sku
            foreach($params['sku'] as $val){
                $specValue = SpecValue::query()->whereIn('spec_value', explode(';', $val['sku']))->get()->toArray();
                $skuIds = array();
                foreach($specValue as $item){
                    $specInfo = array(
                        'goods_id' => $goods->getQueueableId(),
                        'spec_id' => $item['spec_id'],
                        'spec_value_id' => $item['id'],
                    );
                    $goodsSpec = GoodsSpec::query()->firstOrCreate($specInfo);
                    $skuIds[] = $goodsSpec->getQueueableId();
                }

                $skuInfo = array(
                    'goods_id' => $goods->getQueueableId(),
                    'spec_sku_id' => implode(',', $skuIds),
                    'goods_no' => $val['goods_no'] ?? Str::random(6),
                    'goods_thumb' => $val['image']  ?? '',
                    'goods_price' => $val['goods_price']  ?? 0,
                    'line_price' => $val['line_price']  ?? 0,
                    'stock_num' => $val['stock_num']  ?? 0,
                    'goods_sales' => $val['goods_sales']  ?? 0,
                    'goods_weight' => $val['goods_weight']  ?? 0,
                );
                GoodsSku::query()->create($skuInfo);
            }
            \DB::commit();
        } catch (QueryException $exception) {
            \DB::rollBack();
            throw new Exception($exception->getMessage(), $exception->getCode());
        }
        return true;
    }

    /**
     * 商品详情
     * 
     * @author ChenGuangHui
     * @dateTime 2022-06-24
     * @param [type] $data
     * @param [type] $goodsId
     */
    public function show($data, $goodsId)
    {
        $data = Goods::query()->with(['goodsSku', 'goodsSpec'])->where('goods_id', $goodsId)->first();
        abort_if(empty($data), HttpCode::FORBIDDEN, '商品不存在！');
        $goodsInfo = $data->toArray();
        // 属性
        $spec = Spec::query()->whereIn('id', array_unique(array_column($goodsInfo['goods_spec'], 'spec_id')))->get();
        $specValue = SpecValue::query()->whereIn('id', array_unique(array_column($goodsInfo['goods_spec'], 'spec_value_id')))->get()->groupBy('spec_id')->toArray();
        $attribute = $skuInfo = [];
        foreach($spec as $k => $item){
            $attribute[$k] = array(
                'name' => $item['spec_name'],
                'item' => array_column($specValue[$item['id']], 'spec_value'),
            );
        }
        // 规格
        foreach($goodsInfo['goods_sku'] as $k => &$sku){
            $goods_spec = collect($goodsInfo['goods_spec'])->whereIn('id', explode(',', $sku['spec_sku_id']))->toArray();
            $specSku = SpecValue::query()->whereIn('id', array_column($goods_spec, 'spec_value_id'))->get()->toArray();

            $skuInfo[$k] = array(
                "sku" => implode(';', array_column($specSku, 'spec_value')),
                "goods_no" => $sku['goods_no'] ?? '',
                "goods_price" => $sku['goods_price'] ?? '',
                "line_price" => $sku['line_price'] ?? '',
                "stock_num" => $sku['stock_num'] ?? '',
                "goods_sales" => $sku['goods_sales'] ?? '',
                "goods_weight" => $sku['goods_weight'] ?? '',
                "goods_thumb" => $sku['goods_thumb'] ?? '',
                "image" => $sku['goods_thumb']
            );
            $sku["image"] = $sku['goods_thumb'] ?? '';
        }
        $goodsInfo['goods_cover'] = json_decode($goodsInfo['goods_cover'], true);
        $goodsInfo['goods_thumb'] = json_decode($goodsInfo['goods_thumb'], true);
        $goodsInfo['goods_video'] = json_decode($goodsInfo['goods_video'], true);
        $goodsInfo['service_ids'] = explode(',', $goodsInfo['service_ids']);
        return array_merge($goodsInfo, ['sku' => $skuInfo, 'attribute' => $attribute]);
    }

    /**
     * @param $params
     * @param $goodsId
     * @return bool|int
     */
    public function update($params, $goodsId)
    {
        $lockName = 'goods_update_' . auth('api')->id();
        $lock = \Cache::lock($lockName, 5);
        abort_if(!$lock->get(), HttpCode::TOO_MANY_REQUESTS, '请勿重复操作！');

        \DB::beginTransaction();
        try {
            $data = array(
                'goods_name' => $params['goods_name'],
                'goods_price' => $params['goods_price'],
                'line_price' => $params['line_price'],
                'goods_type' => $params['goods_type'],
                'goods_no' => $params['goods_no'],
                'status' => $params['status'],
                'title' => $params['title'] ?? '',
                'freight_id' => $params['freight_id'],
                'service_ids' => implode(',', $params['service_ids']),
                'gift_growth' => $params['gift_growth'] ?? 0,
                'gift_point' => $params['gift_point'] ?? 0,
                'use_point_limit' => $params['use_point_limit'] ?? 0,
                'limit_num' => $params['limit_num'] ?? 0,
                'stock_num' => !empty($params['sku']) ? array_sum(array_column($params['sku'], 'stock_num')) : 0,
                'goods_thumb' => json_encode($params['goods_thumb'], true),
                'goods_cover' => json_encode($params['goods_cover'], true),
                'goods_video' => json_encode($params['goods_video'], true),
                'content' => $params['content'],
                'md_content' => $params['md_content'],
            );
            Goods::query()->where('goods_id', $goodsId)->update($data);

            // 属性
            foreach($params['attribute'] as $val){
                $spec = Spec::query()->firstOrCreate(['spec_name' => $val['name']]);
                foreach($val['item'] as $item){
                    SpecValue::query()->firstOrCreate(['spec_id' => $spec->getQueueableId(), 'spec_value' => $item]);
                }
            }
            // sku
            $skuIds = implode(';', array_column($params['sku'], 'sku'));
            $specValue = SpecValue::query()->whereIn('spec_value', explode(';', $skuIds))->get()->keyBy("spec_value")->toArray();
            foreach($params['sku'] as $val){
                $skuIds = array();
                foreach(explode(';', $val["sku"]) as $item){
                    abort_unless(isset($specValue[$item]), 500, "商品异常！");
                    $goodsSpec = GoodsSpec::query()->where('goods_id', $goodsId)->where('spec_id', $specValue[$item]["spec_id"])->where('spec_value_id', $specValue[$item]["id"])->first();
                    abort_if(empty($goodsSpec), 500, "商品异常！");
                    $skuIds[] = $goodsSpec->id;
                }

                $skuInfo = array(
                    'goods_id' => $goodsId,
                    'spec_sku_id' => implode(',', $skuIds),
                    'goods_no' => $val['goods_no'] ?? 0,
                    'goods_thumb' => $val['image']  ?? '',
                    'goods_price' => $val['goods_price']  ?? 0,
                    'line_price' => $val['line_price']  ?? 0,
                    'stock_num' => $val['stock_num']  ?? 0,
                    'goods_sales' => $val['goods_sales']  ?? 0,
                    'goods_weight' => $val['goods_weight']  ?? 0,
                );
                $goodsSku = GoodsSku::query()->where('goods_id', $goodsId)->where('spec_sku_id', implode(',', $skuIds))->first();
                if (empty($goodsSku)) {
                    GoodsSku::query()->create($skuInfo);
                } else {
                    GoodsSku::query()->where('goods_id', $goodsId)->where('spec_sku_id', implode(',', $skuIds))->update($skuInfo);
                }
            }
            \DB::commit();
        } catch (QueryException $exception) {
            \DB::rollBack();
            throw new Exception($exception->getMessage(), $exception->getCode());
        }

        return true;
    }

    /**
     * @param $goodsId
     * @return bool|mixed|null
     */
    public function destroy($goodsId)
    {
        $data = Goods::query()->where('goods_id', $goodsId)->first();
        abort_if(empty($data), HttpCode::FORBIDDEN, '商品不存在！');
        \DB::beginTransaction();
        try {
            GoodsSku::query()->where('goods_id', $goodsId)->delete();
            GoodsSpec::query()->where('goods_id', $goodsId)->delete();
            Cart::query()->where('goods_id', $goodsId)->delete();
            \DB::commit();
        } catch (QueryException $exception) {
            \DB::rollBack();
            throw new Exception($exception->getMessage(), $exception->getCode());
        }
        return true;
    }
}
